#ifndef PATTERN_H
#define PATTERN_H

#include "basic.h"

//-------------------------------------------------//
//---------------Caculate Fuction------------------//
//-------------------------------------------------//
uint8_t Sub(uint8_t a /*减数*/, uint8_t b /*被减数*/)
{
  a = a % 12;
  b = b % 12;
  uint8_t ret;
  if (a >= b)
    ret = (a - b);
  if (a < b)
    ret = (12 + a - b);
  return ret;
}

uint8_t Add(uint8_t a, uint8_t b)
{
  a = a % 12;
  b = b % 12;
  uint8_t ret;
  if ((a + b) > 11)
    ret = (a + b) - 12;
  if ((a + b) <= 11)
    ret = a + b;
  return ret;
}

//-------------------------------------------------//
//----------------Basic Function-------------------//
//-------------------------------------------------//

void on_order(uint8_t a /*display position a should be add*/, uint8_t h)
{

  leds[Sub(a, 0)] = CHSV(h, 100, 255); // The head
  leds[Sub(a, 1)] = CHSV(h, 100, 125); // The body
  leds[Sub(a, 2)] = CHSV(h, 100, 75);  // The tail
}

void off_order(uint8_t a /*display position a should be sub*/, uint8_t h)
{
  leds[Add(a, 0)] = CHSV(h, 100, 255); // The head
  leds[Add(a, 1)] = CHSV(h, 100, 125); // The body
  leds[Add(a, 2)] = CHSV(h, 100, 75);  // The tail
}

void adjust0(uint8_t time) // Apply to the function that not light all LEDs
{
  FastLED.setBrightness(Brightness);
  FastLED.show();
  time = time + 1;
  uint8_t i;
  for (i = 0; i <= time; i++)
  {
    delay(1);
    Task();
  }
  FastLED.clear();
  FastLED.show();
}
void adjust1(uint8_t time) // Apply to the function that light all LEDs
{
  FastLED.setBrightness(Brightness);
  FastLED.show();
  uint8_t i;
  for (i = 0; i <= time; i++)
  {
    delay(1);
    Task();
  }
}

void clock_print(uint8_t time, uint8_t hue)
{
  switch (time)
  {
  case 1:
    leds[time - 1] = CHSV(hue, 255, 255);
    break;
  case 2:
    leds[time - 1] = CHSV(hue, 255, 255);
    break;
  case 3:
    leds[time - 1] = CHSV(hue, 255, 255);
    break;
  case 4:
    leds[time - 1] = CHSV(hue, 255, 255);
    break;
  case 5:
    leds[time - 1] = CHSV(hue, 255, 255);
    break;
  case 6:
    leds[time - 1] = CHSV(hue, 255, 255);
    break;
  case 7:
    leds[time - 1] = CHSV(hue, 255, 255);
    break;
  case 8:
    leds[time - 1] = CHSV(hue, 255, 255);
    break;
  case 9:
    leds[time - 1] = CHSV(hue, 255, 255);
    break;
  case 10:
    leds[time - 1] = CHSV(hue, 255, 255);
    break;
  case 11:
    leds[time - 1] = CHSV(hue, 255, 255);
    break;
  case 12:
    leds[time - 1] = CHSV(hue, 255, 255);
    break;
  case 0:
    leds[11] = CHSV(hue, 255, 255);
    break;

  default:
    fill_solid(leds, NUM_LEDS, CRGB::Red);
    break;
  }
}

//-------------------------------------------------//
//---------------Pattern Section-------------------//
//-------------------------------------------------//

void Clock(uint8_t h1, uint8_t h2, uint8_t h3) // code 0
{
  if (wifi_check)
  {
    timeClient.update();

    FastLED.clear();
    uint8_t min = timeClient.getMinutes();
    uint8_t sec = timeClient.getSeconds();
    uint8_t hour = timeClient.getHours();

    clock_print(sec / 5, h3);
    clock_print(min / 5, h2);
    clock_print(hour % 12, h1);
    FastLED.setBrightness(Brightness);

    if ((hour != time1) || (min != time2) || (sec != time3))
    {
      FastLED.show();
      time1 = hour;
      time2 = min;
      time3 = sec;

      Serial.print("hour = ");
      Serial.println(hour);
      Serial.print("min = ");
      Serial.println(min);
      Serial.print("sec = ");
      Serial.println(sec);
    }
  }
  else co_pat++;

  // Serial.print("showing");
}

void Inspire() // code 1
{
  uint8_t n = 0;
  for (n = 0; n < 12; n++)
  {
    on_order(Add(0, n++), 120);
    adjust0(40 + 50 / (pace + 1));
  }
}

void Follow5(uint8_t h1, uint8_t h2, uint8_t h3, bool on_off) // code 2
{
  uint8_t n = 0;
  if (on_off)
  {
    for (n = 0; n < 12; n++)
    {
      on_order(Add(0, n), h1);
      on_order(Add(4, n), h2);
      on_order(Add(8, n), h3);
      adjust0(pace);
    }
  }
  else
  {
    for (n = 0; n < 12; n++)
    {
      off_order(Sub(0, n), h1);
      off_order(Sub(4, n), h2);
      off_order(Sub(8, n), h3);
      adjust0(pace);
    }
  }
}

void Follow6(uint8_t h1, uint8_t h2) // code 3
{
  uint8_t count;
  for (count = 0; count < 37; count++)
  {
    on_order(Add(5, count), h1);
    off_order(Sub(5, count), h2);
    adjust0(pace);
  }

  for (count = 0; count < 7; count++)
  {
    fill_gradient_RGB(leds, 5, CHSV(h1, 100, 100), Add(5, count), CHSV(h2, 100, 100));
    fill_gradient_RGB(leds, Sub(5, count), CHSV(h2, 100, 100), 5, CHSV(h1, 100, 100));
    adjust0(pace);
  }
}

void Breath_lamp(uint8_t hue) // 每pace 秒呼吸一次60  pace=60/x //code 4
{
  fill_solid(leds, NUM_LEDS, CHSV(hue, 100, 100));
  FastLED.setBrightness(beatsin8(60 / pace, 10, Brightness));
  FastLED.show();
}

void Breath_with_colorchange(uint8_t hue) // 每pace 秒呼吸一次60  pace=60/x //code 5
{
  uint8_t change = hue;
  uint8_t bright;
  for (uint8_t i = 0; i <= 255; i++)
  {
    fill_solid(leds, NUM_LEDS, CHSV(change++, 100, 100));
    bright += 3;
    FastLED.setBrightness(bright);
    adjust0(pace);
  }
}

void Colorful_change() // 所有灯是一个颜色然后变化 //code 6
{
  uint8_t i = 0;
  for (i = 0; i < 256; i++)
  {
    fill_solid(leds, NUM_LEDS, CHSV(i, 240, 255));
    adjust1(pace);
  }
}

void Party_leap() // code 7
{
  int pos = random8(NUM_LEDS);
  EVERY_N_MILLISECONDS(100)
  {
    if (random8() < 80)
    {
      leds[pos] = ColorFromPalette(PartyColors_p, random8(255), 128, LINEARBLEND);
    }
  }
  EVERY_N_MILLISECONDS(20)
  {
    fadeToBlackBy(leds, NUM_LEDS, 10);
  }
  FastLED.show();
  delay(50);
}

void Flow_rainbow() // code 8
{
  uint8_t count;
  for (count = 0; count < 256; count++)
  {
    fill_rainbow(leds, NUM_LEDS, count++, 35);
    adjust1(pace);
  }
}

void Fill_light() // code 9
{
  fill_solid(leds, NUM_LEDS, CRGB::White);
  adjust0(1);
}


void switchpattern()
{
  if (co_pat>9)
  {
    co_pat=0;
  }
  
  switch (co_pat)
  {
  case 0:
    Clock(12, 56, 237);
    break;
  case 1:
    Inspire();
    break;
  case 2:
    Follow5(123, 222, 12, 1);
    break;
  case 3:
    Follow6(123, 222);
    break;
  case 4:
    Breath_lamp(79);
    break;
  case 5:
    Breath_with_colorchange(125);
    break;
  case 6:
    Colorful_change();
    break;
  case 7:
    Party_leap();
    break;
  case 8:
    Flow_rainbow();
    break;
  case 9:
    Fill_light();
    break;

  default:
    break;
  }
}


#endif
